package cn.h8k.hj212;

import cn.h8k.hj212.codec.Hj212Encoder;
import cn.h8k.hj212.codec.Hj212Decoder;
import cn.h8k.hj212.codec.Hj212Validator;
import cn.h8k.hj212.codec.impl.DefaultHj212Encoder;
import cn.h8k.hj212.codec.impl.DefaultHj212Decoder;
import cn.h8k.hj212.codec.impl.DefaultHj212Validator;
import cn.h8k.hj212.constant.Hj212Constants;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * HJ212协议编解码器
 * 实现HJ212-2017协议的编码和解码功能
 * 使用策略模式组合编码器、解码器和校验器
 * 可被继承以自定义编解码行为
 */
public class Hj212Codec {
    
    private final Hj212Encoder encoder;
    private final Hj212Decoder decoder;
    private final Hj212Validator validator;
    
    /**
     * 默认构造函数，使用默认的编码器、解码器和校验器
     */
    public Hj212Codec() {
        this.encoder = new DefaultHj212Encoder();
        this.decoder = new DefaultHj212Decoder();
        this.validator = new DefaultHj212Validator();
    }
    
    /**
     * 自定义构造函数，使用指定的编码器、解码器和校验器
     * @param encoder 编码器
     * @param decoder 解码器
     * @param validator 校验器
     */
    public Hj212Codec(Hj212Encoder encoder, Hj212Decoder decoder, Hj212Validator validator) {
        this.encoder = encoder;
        this.decoder = decoder;
        this.validator = validator;
    }
    
    /**
     * 编码：将数据字典转为HJ212协议字符串
     * @param dic 包含协议字段的Map
     * @return 符合HJ212-2017标准的协议字符串
     */
    public String encode(Map<String, Object> dic) {
        String data = encoder.encode(dic);
        
        // 构建完整的协议字符串
        StringBuilder result = new StringBuilder();
        result.append(Hj212Constants.HEAD);
        result.append(String.format(Hj212Constants.LENGTH_FORMAT, data.length()));
        result.append(data);
        result.append(validator.calculateCrc(data).toUpperCase());
        result.append(Hj212Constants.LINE_ENDING);
        
        return result.toString();
    }

    /**
     * 解码：将HJ212协议字符串转为数据字典
     * @param data HJ212协议字符串
     * @return 解析后的数据字典
     * @throws IllegalArgumentException 当数据长度或CRC校验失败时抛出异常
     */
    public Map<String, Object> decode(String data) {
        int length = Integer.parseInt(data.substring(2, 6));
        String body = data.substring(6, 6 + length);
        String crc = data.substring(data.length() - 6, data.length() - 2);
        
        // 数据长度验证
        if (!validator.validateLength(body, length)) {
            throw new IllegalArgumentException(Hj212Constants.ERROR_LENGTH_VALIDATION);
        }
        
        // CRC校验
        if (!validator.validateCrc(body, crc)) {
            throw new IllegalArgumentException(Hj212Constants.ERROR_CRC_VALIDATION);
        }
        
        // 使用解码器解析数据
        return decoder.decode(data);
    }

    /**
     * 获取时间戳，格式：年月日时分秒毫秒
     * @return 格式化的时间戳字符串
     */
    public static String getTimeStamp() {
        SimpleDateFormat sdf = new SimpleDateFormat(Hj212Constants.TIMESTAMP_FORMAT);
        Date now = new Date();
        String timestamp = sdf.format(now);
        
        // 添加毫秒
        long ms = now.getTime() % 1000;
        return timestamp + String.format(Hj212Constants.MILLISECOND_FORMAT, ms);
    }

    /**
     * 获取校验器
     * @return 校验器实例
     */
    public Hj212Validator getValidator() {
        return validator;
    }
    
    /**
     * 保护方法：子类可重写以自定义协议头构建
     * @param length 数据长度
     * @return 协议头字符串
     */
    protected String buildProtocolHeader(int length) {
        return Hj212Constants.HEAD + String.format(Hj212Constants.LENGTH_FORMAT, length);
    }
    
    /**
     * 保护方法：子类可重写以自定义协议尾构建
     * @param crc CRC校验码
     * @return 协议尾字符串
     */
    protected String buildProtocolFooter(String crc) {
        return crc + Hj212Constants.LINE_ENDING;
    }
} 